#include "stdafx.h"
#include "TombolaPage.h"
#include "ui_MainWindow.h"
#include "Config.h"
#include "BarcodeDecoderThread.h"

using namespace std;
using namespace AirCrash::Calypso;

TombolaPage::TombolaPage() : mUi(0), mBackgroundImage(Config::get("Background", "image").toString()), mCurrentItem(0), 
	mBlockInput(false), mBlocked(false), mCodeThread(new CodeThread()), mMouseDownInCodeInput(false)/*, mDecoderThread(new BarcodeDecoderThread())*/ {

	mGrayBackground = makeGrayScaleImage(mBackgroundImage);

	connect( mCodeThread, SIGNAL(result(QString, QImage, bool)), this, SLOT(databaseResult(QString, QImage, bool)) );
	connect( &mTimeTimer, SIGNAL(timeout()), this, SLOT(setTime()) );
	connect( &mEmptyTimer, SIGNAL(timeout()), this, SLOT(gotoNew()) );
	mEmptyTimer.setInterval(Config::get("Settings", "timeToNew").toInt() * 1000);
	mEmptyTimer.setSingleShot(true);
}

TombolaPage::~TombolaPage() {
	mTimeTimer.stop();

	mCodeThread->wait();
	delete mCodeThread;

	/*mDecoderThread->interrupt();
	mDecoderThread->wait();
	delete mDecoderThread;*/
}

void TombolaPage::keyPressEvent(QKeyEvent * e) {
	if (!mBlockInput && !mBlocked) {
		switch (e->key()) {
			case Qt::Key_0:
				mInputCode += "0";
				break;
			case Qt::Key_1:
				mInputCode += "1";
				break;
			case Qt::Key_2:
				mInputCode += "2";
				break;
			case Qt::Key_3:
				mInputCode += "3";
				break;
			case Qt::Key_4:
				mInputCode += "4";
				break;
			case Qt::Key_5:
				mInputCode += "5";
				break;
			case Qt::Key_6:
				mInputCode += "6";
				break;
			case Qt::Key_7:
				mInputCode += "7";
				break;
			case Qt::Key_8:
				mInputCode += "8";
				break;
			case Qt::Key_9:
				mInputCode += "9";
				break;
			case Qt::Key_Backspace:
				mInputCode.remove(mInputCode.size() - 1, 1);
				break;
			case Qt::Key_Return:
			case Qt::Key_Enter:
				getCode();
				break;
		}
		showCurrentCodeInfo();
	}
}

void TombolaPage::paintEvent(QPaintEvent * e) {
	QPainter painter(this);
	painter.setRenderHint(QPainter::SmoothPixmapTransform);
	painter.setRenderHint(QPainter::Antialiasing);
	painter.setRenderHint(QPainter::HighQualityAntialiasing);

	painter.fillRect(rect(), QColor(Config::get("Backgound", "color").toString()));
	if (!mBlockInput && !mBlocked) {
		painter.drawImage(mBackArea, mBackgroundImage);
	} else {
		painter.drawImage(mBackArea, mGrayBackground);
	}
}

void TombolaPage::showEvent(QShowEvent * e) {	
	if (mUi) {
		mUi->mMenuBar->setVisible(false);
		mBlockInput = false;
		setFocus();
		mCurrentItem = mCodeInfo.size();
		setTime();
		//mUi->mOpenCvWidget->startCamera();
		//mDecoderThread->start();
	}
}

void TombolaPage::hideEvent(QHideEvent * e) {
	mUi->mMenuBar->setVisible(true);
	//mDecoderThread->interrupt();
	mTimeTimer.stop();
	/*if (mUi) {
		mUi->mOpenCvWidget->startCamera();
	}*/
}

void TombolaPage::gotoNew() {
	mCurrentItem = mCodeInfo.size();
	showCurrentCodeInfo();
}

void TombolaPage::setUi(Ui::MainWindowClass * ui, float scale) {
	mUi = ui;
	mScale = scale;

	//mDecoderThread->setCamera(mUi->mOpenCvWidget);

	mUi->mMenuBar->setVisible(false);

	mUi->mNumpadWidget->hide();
	mUi->mSearchOverlayWidget->hide();

	mLeftPos = ((this->width() - mBackgroundImage.width() * mScale) / 2);
	mTextFont = QFont("Verdana");
	mTextFont.setPixelSize(40 * scale);

	mBackArea = scaleRect(mBackgroundImage.rect(), scale);
	mBackArea.moveLeft(mLeftPos);

	mUi->mSearchOverlayWidget->setGeometry(mBackArea);

	mUi->mNumpadWidget->setGeometry(scaleRect(Config::get("Numpad", "area").toRect(), scale));
	mUi->mNumpadWidget->move(mUi->mNumpadWidget->pos().x() + mLeftPos, mUi->mNumpadWidget->pos().y());

	mUi->mPrevCode->setGeometry(scaleRect(Config::get("Layout", "previousButton").toRect(), scale));
	mUi->mPrevCode->move(mUi->mPrevCode->pos().x() + mLeftPos, mUi->mPrevCode->pos().y());

	mUi->mNextCode->setGeometry(scaleRect(Config::get("Layout", "nextButton").toRect(), scale));
	mUi->mNextCode->move(mUi->mNextCode->pos().x() + mLeftPos, mUi->mNextCode->pos().y());

	mUi->mCodeInput->setGeometry(scaleRect(Config::get("Layout", "codeArea").toRect(), scale));
	mUi->mCodeInput->move(mUi->mCodeInput->pos().x() + mLeftPos, mUi->mCodeInput->pos().y());
	mUi->mCodeInput->setFont(mTextFont);

	mUi->mSummary->setGeometry(scaleRect(Config::get("Layout", "summaryArea").toRect(), scale));
	mUi->mSummary->move(mUi->mSummary->pos().x() + mLeftPos, mUi->mSummary->pos().y());
	mUi->mSummary->setFont(mTextFont);

	mUi->mImage->setGeometry(scaleRect(Config::get("Layout", "imageArea").toRect(), scale));
	mUi->mImage->move(mUi->mImage->pos().x() + mLeftPos, mUi->mImage->pos().y());

	mTextFont.setPixelSize(Config::get("Time", "fontSize").toInt() * scale);
	mUi->mTime->setGeometry(scaleRect(Config::get("Time", "area").toRect(), scale));
	mUi->mTime->move(mUi->mTime->pos().x() + mLeftPos, mUi->mTime->pos().y());
	mUi->mTime->setFont(mTextFont);

	mTextFont.setPixelSize(Config::get("Layout", "totalFontSize").toInt() * scale);
	mUi->mTotalToday->setGeometry(scaleRect(Config::get("Layout", "totalArea").toRect(), scale));
	mUi->mTotalToday->move(mUi->mTotalToday->pos().x() + mLeftPos, mUi->mTotalToday->pos().y());
	mUi->mTotalToday->setFont(mTextFont);

	QSqlQuery query("SELECT COUNT(Id) FROM Scanned WHERE Date LIKE '" + QDate::currentDate().toString("dd-MM-yyyy") + "%'");
	query.first();
	mTotalCodes = query.value(0).toInt();
	qDebug() << query.executedQuery();
	mUi->mTotalToday->setText(QString::number(mTotalCodes));

	static bool firstConnect(true);
	if (firstConnect) {
		connect (mUi->mPrevCode, SIGNAL(clicked()), this, SLOT(previous()) );
		connect (mUi->mNextCode, SIGNAL(clicked()), this, SLOT(next()) );
		connect (mUi->mNumpadWidget, SIGNAL(numpadInsert(const QString&)), this, SLOT(numpadInsert(const QString&)) );
		connect (mUi->mNumpadWidget, SIGNAL(numpadDelete()), this, SLOT(numpadDelete()) );
		connect (mUi->mNumpadWidget, SIGNAL(numpadGetCode()), this, SLOT(numpadGetCode()) );

		firstConnect = false;
	}

	showCurrentCodeInfo();
	setTime();
}

void TombolaPage::getCode() {
	if (!mInputCode.isEmpty()) {
		qDebug() << "Get the code " << mInputCode;

		mUi->mSearchOverlayWidget->show();
		mBlockInput = true;
		mCurrentItem = mCodeInfo.size();
		repaint();
		mCodeThread->getCode(mInputCode.toInt());
	}
}

void TombolaPage::databaseResult(QString summary, QImage image, bool alreadyUsed) {
	qDebug() << "Result: " << (summary != "" ? summary : "Not found");
	mUi->mSearchOverlayWidget->hide();
	CodeInfo codeInfo;
	codeInfo.mCode = mInputCode.toInt();
	codeInfo.mSummary = summary;
	codeInfo.mAlreadyUsed = alreadyUsed;
	if (!image.isNull()) {
		codeInfo.mImage = image.scaled(mUi->mImage->size(), Qt::KeepAspectRatio);
	}
	mCodeInfo.push_back(codeInfo);

	mInputCode.clear();
	mBlockInput = false;

	if (mCodeInfo.size() > 10) {
		mCodeInfo.pop_front();
	}

	if (!alreadyUsed) {
		++mTotalCodes;
		mUi->mTotalToday->setText(QString::number(mTotalCodes));
	}
	mCurrentItem = mCodeInfo.size() - 1;
	showCurrentCodeInfo();
}

void TombolaPage::previous() {
	if (mCurrentItem > 0) {
		qDebug() << "Previous code";
		--mCurrentItem;
		showCurrentCodeInfo();
	}
}

void TombolaPage::next() {
	if (mCurrentItem < mCodeInfo.size()) {
		qDebug() << "Next code";
		++mCurrentItem;
		showCurrentCodeInfo();
	}
}

void TombolaPage::deleteLast() {
	if (!mCodeInfo.empty()) {
		QSqlQuery query("DELETE FROM Scanned WHERE Code = " + QString::number(mCodeInfo.back().mCode));
		mCodeInfo.pop_back();
		mCurrentItem = mCodeInfo.empty() ? 0 : mCodeInfo.size() - 1;
		--mTotalCodes;
		mUi->mTotalToday->setText(QString::number(mTotalCodes));
		showCurrentCodeInfo();
	}
}

void TombolaPage::setBlocked(bool blocked) {
	mBlocked = blocked;
	repaint();
}

void TombolaPage::showCurrentCodeInfo() {
	if (mCurrentItem < mCodeInfo.size()) {
		if (mInputCode.isEmpty()) {
			mUi->mCodeInput->setText(QString::number(mCodeInfo.at(mCurrentItem).mCode));
		} else {
			mUi->mCodeInput->setText(mInputCode);
		}

		if (mCodeInfo.at(mCurrentItem).mSummary.isEmpty()) {
			mUi->mSummary->setText("Niet gevonden");
		} else {
			mUi->mSummary->setText(mCodeInfo.at(mCurrentItem).mSummary);
		}

		if (!mCodeInfo.at(mCurrentItem).mImage.isNull()) {
			if (mCodeInfo.at(mCurrentItem).mAlreadyUsed) {
				mUi->mSummary->setStyleSheet("color:red;");
				mUi->mImage->setPixmap( QPixmap::fromImage(makeGrayScaleImage(mCodeInfo.at(mCurrentItem).mImage)) );
			} else {
				mUi->mSummary->setStyleSheet("color:black;");
				mUi->mImage->setPixmap(QPixmap::fromImage(mCodeInfo.at(mCurrentItem).mImage));
			}
		} else {
			mUi->mImage->setPixmap(QPixmap());
		}
		mEmptyTimer.start();
	} else {
		mEmptyTimer.stop();
		mUi->mCodeInput->setText(mInputCode);
		mUi->mSummary->clear();
		mUi->mImage->setPixmap(QPixmap());
	}
	setButtonsVisibility();
}

void TombolaPage::setButtonsVisibility() {
	if (mCurrentItem == mCodeInfo.size()) {
		mUi->mNextCode->setVisible(false);
	} else {
		mUi->mNextCode->setVisible(true);
	}
	if (mCurrentItem == 0) {
		mUi->mPrevCode->setVisible(false);
	} else {
		mUi->mPrevCode->setVisible(true);
	}
}

void TombolaPage::setTime() {
	QDateTime time(QDateTime::currentDateTime());
	mUi->mTime->setText( time.toString(Config::get("Time", "format").toString()) );
	mTimeTimer.start((60 - time.time().second()) * 1000);
}

void TombolaPage::numpadInsert(const QString& number) {
	if (!mBlockInput && !mBlocked) {
		mInputCode += number;
	}
	showCurrentCodeInfo();
}

void TombolaPage::numpadDelete() {
	if (!mBlockInput && !mBlocked) {
		mInputCode.remove(mInputCode.size() - 1, 1);
	}
	showCurrentCodeInfo();
}

void TombolaPage::numpadGetCode() {
	if (!mBlockInput && !mBlocked) {
		mUi->mNumpadWidget->hide();
		getCode();
	}
}

void TombolaPage::mousePressEvent(QMouseEvent * e) {
	if ( mUi->mCodeInput->geometry().contains(e->globalPos()) ) {
		mMouseDownInCodeInput = true;
	}
}

void TombolaPage::mouseReleaseEvent(QMouseEvent * e) {
	if ( mUi->mCodeInput->geometry().contains(e->globalPos()) && mMouseDownInCodeInput) {
		if (mUi->mNumpadWidget->isVisible()) {
			mUi->mNumpadWidget->hide();
		} else {
			mUi->mNumpadWidget->show();
		}
	}
	if (mCurrentItem < mCodeInfo.size()) {
		mEmptyTimer.start();
	}
	mMouseDownInCodeInput = false;
}

void TombolaPage::mouseMoveEvent(QMouseEvent * e) {
	if (e->globalY() < 10 && !mUi->mMenuBar->isVisible()) {
		mUi->mMenuBar->setVisible(true);
	} else if (e->globalY() > 10 && mUi->mMenuBar->isVisible()) {
		mUi->mMenuBar->setVisible(false);
	}
}

namespace AirCrash {
namespace Calypso {

CodeThread::CodeThread() {
}

CodeThread::~CodeThread() {
}

void CodeThread::getCode(int code) {
	mCode = code;
	start();
}

void CodeThread::run() {
	QTime timer;
	timer.start();
	int timeToWait(Config::get("Settings", "waitTimeScannedCode").toInt());

	QSqlQuery query("SELECT Items.Image, Items.Summary, Scanned.Date FROM Codes INNER JOIN Items ON Codes.ItemId = Items.Id LEFT OUTER JOIN Scanned ON Codes.Id = Scanned.Code WHERE Codes.Id = " + QString::number(mCode));

	if (!query.first()) {
		qDebug() << "Error: " << query.lastError().text();
		int elapsed(timer.elapsed());
		if (elapsed < timeToWait) {
			QThread::msleep(timeToWait - elapsed);
		}
		emit result("", QImage(), false);
	} else {
		QImage image;
		bool alreadyUsed(!query.record().isNull("Date"));
		image.loadFromData(query.record().value("Image").toByteArray(), "PNG");
		QString summary(query.record().value("Summary").toString());
		
		QPainter painter(&image);
		painter.setRenderHint(QPainter::SmoothPixmapTransform);
		painter.setRenderHint(QPainter::Antialiasing);
		painter.setRenderHint(QPainter::HighQualityAntialiasing);

		if (Config::get("Image", "overlayType").toString() == "Text") {
			QFont font("Verdana", Config::get("Image", "overlayTextSize").toInt());
			QFontMetrics fm(font);
			QString overlayText(Config::get("Image", "overlayText").toString());
			overlayText = " " + overlayText + " ";

			QRect textRect(Config::get("Image", "overlayPos").toRect());
			if (textRect.width() > image.width()) {
				textRect.setWidth(image.width());
			}

			painter.setFont(font);
			painter.setPen( QColor(Config::get("Image", "overlayTextColor").toString()) );
			painter.fillRect(textRect, QColor(0,0,0,90));
			painter.drawText(textRect, Config::get("Image", "overlayAlign").toInt(), overlayText);
		} else if (Config::get("Image", "overlayType").toString() == "Image") {
			painter.drawImage( Config::get("Image", "overlayPos").toPoint(), QImage(Config::get("Image", "overlayImage").toString()) );
		}

		if (!alreadyUsed) {
			query.exec("INSERT INTO Scanned (Code, Date) VALUES (" + QString::number(mCode) + ", '" + QDateTime::currentDateTime().toString("dd-MM-yyyy hh:mm:ss") + "')");	
		} else {
			QFont font("times new roman,utopia");
			QPainterPath path;
			QString text("Al Weg");

			font.setStyleStrategy(QFont::ForceOutline);
			font.setPixelSize(150);
			font.setStyleHint(QFont::Times);
			path.addText(0, 0, font, text);
			
			QFontMetrics metrics(font);
			QRectF br(metrics.boundingRect(text));
			QPointF center(br.center());
			QPointF centerPoint(image.rect().center());

			painter.translate(centerPoint - center);
			painter.translate(center);
			painter.rotate(-30);
			painter.translate(-center);

			painter.fillPath(path, Qt::white);
			painter.setPen(QPen(QBrush(Qt::black), 2));
			painter.drawPath(path);
		}

		int elapsed(timer.elapsed());
		if (elapsed < timeToWait) {
			QThread::msleep(timeToWait - elapsed);
		}
		emit result(summary, image, alreadyUsed);
	}
}

}
}